package rules

import (
	"fmt"
	"strings"
	"sync"
)

// CheckStatus 检查状态枚举
type CheckStatus int

const (
	StatusPassed  CheckStatus = iota // 通过
	StatusFailed                     // 失败
	StatusSkipped                    // 跳过
)

// String 返回状态的字符串表示
func (s CheckStatus) String() string {
	switch s {
	case StatusPassed:
		return "通过"
	case StatusFailed:
		return "失败"
	case StatusSkipped:
		return "跳过"
	default:
		return "未知"
	}
}

// CheckResult 检查结果
type CheckResult struct {
	Status  CheckStatus
	Message string
	Details []string
}

// DDLCheckData DDL检查数据
type DDLCheckData struct {
	Schema         string
	Table          string
	Script         string
	RollbackScript string
}

// Rule 检查规则接口
type Rule interface {
	Name() string
	Check(data DDLCheckData) CheckResult
}

// RuleEngine 规则引擎
type RuleEngine struct {
	rules []Rule
}

// NewRuleEngine 创建规则引擎
func NewRuleEngine() *RuleEngine {
	return &RuleEngine{
		rules: []Rule{
			&DatabaseComplianceRule{},
			&FieldCommentRule{},
			&RollbackScriptComplianceRule{},
			&TableRelationshipRule{},
			&RollbackTableRelationshipRule{},
			&ExternalAPIRule{},
		},
	}
}

// Execute 执行所有规则检查（异步并发执行）
func (engine *RuleEngine) Execute(data DDLCheckData) map[string]CheckResult {
	results := make(map[string]CheckResult)
	var wg sync.WaitGroup
	var mu sync.Mutex

	// 为每个规则启动一个goroutine
	for _, rule := range engine.rules {
		wg.Add(1)
		go func(r Rule) {
			defer wg.Done()

			// 执行规则检查
			result := r.Check(data)

			// 使用互斥锁保护并发写入
			mu.Lock()
			results[r.Name()] = result
			mu.Unlock()
		}(rule)
	}

	// 等待所有规则检查完成
	wg.Wait()

	return results
}

// GetAllRules 获取所有规则
func (engine *RuleEngine) GetAllRules() []Rule {
	return engine.rules
}

// FormatCheckResult 格式化检查结果
func FormatCheckResult(results map[string]CheckResult) string {
	var builder strings.Builder

	// 首先显示各个检查项目的状态摘要（每项之间不要有空行）
	ruleNames := []string{"DDL验证结果", "字段注释检查", "回滚脚本规范检查", "表关联检查", "回滚脚本表关联检查", "外部API检查"}

	for _, ruleName := range ruleNames {
		if result, exists := results[ruleName]; exists {
			switch result.Status {
			case StatusPassed:
				builder.WriteString(fmt.Sprintf("- ✅ %s\n", ruleName))
			case StatusFailed:
				builder.WriteString(fmt.Sprintf("- ❌ %s\n", ruleName))
			case StatusSkipped:
				builder.WriteString(fmt.Sprintf("- ⚠️ %s 【跳过检查】\n", ruleName))
			}
		}
	}

	builder.WriteString("\n以下再展示详情结果\n")

	// 然后显示详细结果，使用简化的标题并保持紧凑格式
	// 合并DDL相关检查结果
	var ddlDetails []string
	if ddlResult, exists := results["DDL验证结果"]; exists {
		for _, detail := range ddlResult.Details {
			if strings.TrimSpace(detail) != "" && !strings.Contains(detail, "###") {
				ddlDetails = append(ddlDetails, strings.TrimSpace(detail))
			}
		}
	}
	if tableResult, exists := results["表关联检查"]; exists {
		for _, detail := range tableResult.Details {
			if strings.TrimSpace(detail) != "" && !strings.Contains(detail, "###") {
				ddlDetails = append(ddlDetails, strings.TrimSpace(detail))
			}
		}
	}

	if len(ddlDetails) > 0 {
		builder.WriteString("\n## DDL\n")
		for i, detail := range ddlDetails {
			builder.WriteString(fmt.Sprintf("%d. %s\n", i+1, detail))
		}
	}

	// 字段注释检查结果
	if fieldCommentResult, exists := results["字段注释检查"]; exists {
		builder.WriteString("\n## 字段注释检查\n")
		for i, detail := range fieldCommentResult.Details {
			if strings.TrimSpace(detail) != "" && !strings.Contains(detail, "###") {
				builder.WriteString(fmt.Sprintf("%d. %s\n", i+1, detail))
			}
		}
	}

	// 合并rollback相关检查结果
	var rollbackDetails []string
	if rollbackResult, exists := results["回滚脚本规范检查"]; exists {
		for _, detail := range rollbackResult.Details {
			if strings.TrimSpace(detail) != "" && !strings.Contains(detail, "###") {
				rollbackDetails = append(rollbackDetails, strings.TrimSpace(detail))
			}
		}
	}
	if rollbackTableResult, exists := results["回滚脚本表关联检查"]; exists {
		for _, detail := range rollbackTableResult.Details {
			if strings.TrimSpace(detail) != "" && !strings.Contains(detail, "###") {
				rollbackDetails = append(rollbackDetails, strings.TrimSpace(detail))
			}
		}
	}

	if len(rollbackDetails) > 0 {
		builder.WriteString("\n## rollback\n")
		for i, detail := range rollbackDetails {
			builder.WriteString(fmt.Sprintf("%d. %s\n", i+1, detail))
		}
	}

	// API检查结果
	if apiResult, exists := results["外部API检查"]; exists {
		builder.WriteString("\n## API\n")
		for _, detail := range apiResult.Details {
			if strings.TrimSpace(detail) != "" && !strings.Contains(detail, "###") {
				builder.WriteString(detail)
				builder.WriteString("\n")
			}
		}
	}

	return builder.String()
}
